<template>
    <div>
      <n-card>
        <n-space style="margin-bottom: 10px;" justify="space-between">
            <n-button type="primary" @click="initForm('SD');  resourceModalShow = true">新增绘画资源</n-button>

        </n-space>
        <n-grid :x-gap="5" y-gap="5">
          <n-grid-item :span="6" v-for="resource in  resourceInfo">
            <n-card :title="resource.name">
              <template #cover>
                <n-space justify="center">
                  <n-image v-if="resource.type==='MJ'" height="300"  :src="mjPng" :object-fit="'cover'"  :preview-disabled="true"/>
                  <n-image v-if="resource.type==='SD'"  height="300" :src="sdPng" :object-fit="'cover'" :preview-disabled="true"/>
                  <n-image v-if="resource.type==='Fooocus'"   height="300" :src="fooocusPng" :object-fit="'cover'" :preview-disabled="true"/>
                </n-space>
              </template>
              <template #header-extra>
                <n-tag type="primary">
                  {{resource.type}}
                </n-tag>
              </template>
              <template #footer>
                <n-grid>
                  <n-grid-item :span="18">
                    <n-tag type="info" bordered>{{`队列:`+resource.obj.queueSize}}</n-tag>
                    <n-tag type="info" bordered style="margin-left: 5px;">{{`并发:`+resource.obj.coreSize}}</n-tag>
                  </n-grid-item>
                  <n-grid-item :span="6" v-if="resource.type=='SD'">
                    <n-space justify="end">
                      <n-button size="small" type="primary" @click="selectdResourceId = resource.id;modelManagerShow = true">模型照片</n-button>
                    </n-space>
                  </n-grid-item>
                </n-grid>
              </template>
              <template #action>
                <n-space justify="space-between">
                  <n-space>
                    <n-button size="small" type="warning" @click="resourceEdit(resource)">修改</n-button>
                    <n-button size="small" type="error" @click="resourceDeleteById(resource)">删除</n-button>
                    <n-badge v-if="resource.type==='SD' && resource.pluginInfo" :value="resource.pluginInfo.warningCount">
                      <n-button size="small" type="warning" :loading="pluginLoading" @click="selectedSD = resource ;showPluginModal = true">插件</n-button>
                    </n-badge>
                  </n-space>
                  <n-space>
                    <n-button size="small" type="success" v-if="resource.type==='MJ' " @click="resourceTest(resource)" :loading="resource.loading"> 连接</n-button>
                    <n-button size="small" type="success" v-else @click="resourceTest(resource)" :loading="resource.loading"> 测试</n-button>
                  </n-space>
                </n-space>
              </template>
            </n-card>
          </n-grid-item>
        </n-grid>
      </n-card>
      <n-drawer v-model:show="resourceModalShow" :width="800">
        <n-drawer-content :title="resourceForm.id?'修改绘画资源':'新增绘画资源'" closable>
          <n-h6>请选绘图资源类型</n-h6>
          <n-grid :x-gap='5'>
            <n-grid-item :span="8" @click="initForm('SD');resourceForm.type='SD'">
              <n-card :header-style="{padding: '5px 5px 5px 5px'}" :content-style="{padding: '0px 0px 0px 0px'}" title="StableDiffusion">
                <template #cover>
                  <n-image :height="200" :src="sdPng" :object-fit="'cover'" :preview-disabled="true"></n-image>
                </template>
                <n-el :style=" {background: (resourceForm.type==='SD'?'var(--primary-color-hover)' : ''), padding:' 5px 5px 5px 5px' }">
                  <n-space>
                    <n-tag :bordered="false">老司机专属</n-tag>
                    <n-tag :bordered="false">自定义DIY</n-tag>
                    <n-tag :bordered="false">10系显卡,显存6g以上</n-tag>
                  </n-space>
                </n-el>
              </n-card>
            </n-grid-item>
            <n-grid-item :span="8" @click="initForm('SD');resourceForm.type='Fooocus'">
              <n-card :header-style="{padding: '5px 5px 5px 5px'}" :content-style="{padding: '0px 0px 0px 0px'}" title="Fooocus" @click="">
                <template #cover>
                  <n-image :height="200" :src="fooocusPng" :object-fit="'cover'" :preview-disabled="true"></n-image>
                </template>
                <n-el :style=" {background: (resourceForm.type==='Fooocus'?'var(--primary-color-hover)' : ''), padding:' 5px 5px 5px 5px' }">
                  <n-space>
                    <n-tag  :bordered="false">新手福音</n-tag>
                    <n-tag  :bordered="false">本质为SDXL</n-tag>
                    <n-tag  :bordered="false">20系显卡,显存8g以上</n-tag>
                  </n-space>
                </n-el>
              </n-card>
            </n-grid-item>
            <n-grid-item :span="8" @click="initForm('MJ');resourceForm.type='MJ'">
              <n-card :header-style="{padding: '5px 5px 5px 5px'}" :content-style="{padding: '0px 0px 0px 0px'}" title="MidJourney">
                <template #cover>
                  <n-image  :height="200" :src="mjPng" :object-fit="'cover'" :preview-disabled="true"></n-image>
                </template>
                <n-el :style=" {background: (resourceForm.type==='MJ'?'var(--primary-color-hover)' : ''), padding:' 5px 5px 5px 5px' }">
                <n-space>
                  <n-tag  :bordered="false">花小钱办大事</n-tag>
                  <n-tag  :bordered="false">最可控的AI生图</n-tag>
                  <n-tag  :bordered="false">云服务,没有显卡要求</n-tag>
                </n-space>
                </n-el>
              </n-card>
            </n-grid-item>
          </n-grid>
          <n-h6>请填写资源{{resourceForm.type}}信息</n-h6>
          <n-form v-if="resourceForm.type=='MJ'" label-align="left" label-placement="left" label-width="80">
            <n-grid x-gap="5" y-gap="5">
              <n-grid-item :span="24">
                <n-form-item  label="资源名称" path="resourceName">
                  <n-input v-model:value="resourceForm.resourceName" clearable placeholder="请输入资源名称"/>
                </n-form-item>
              </n-grid-item>
              <n-grid-item :span="12">
                <n-form-item label="guildId" path="guildId">
                  <n-input v-model:value="resourceForm.guildId" clearable placeholder="请输入guild-id"/>
                </n-form-item>
              </n-grid-item>
              <n-grid-item :span="12">
                <n-form-item   label="channel-id" path="channel-id">
                  <n-input v-model:value="resourceForm.channelId" clearable placeholder="请输入channel-id"/>
                </n-form-item>
              </n-grid-item>
              <n-grid-item :span="24">
                <n-form-item label="user-token" path="user-token">
                  <n-input v-model:value="resourceForm.userToken" clearable placeholder="请输入guild-id"/>
                </n-form-item>
              </n-grid-item>
              <n-grid-item :span="12">
                <n-form-item label="代理IP" path="proxyIp">
                  <n-input v-model:value="resourceForm.proxyIp" clearable placeholder="请输入代理IP"/>
                </n-form-item>
              </n-grid-item>
              <n-grid-item :span="12">
                <n-form-item label="代理端口" path="proxyPort">
                  <n-input v-model:value="resourceForm.proxyPort" clearable placeholder="请输入代理端口"/>
                </n-form-item>
              </n-grid-item>
              <n-grid-item :span="24">
                <n-collapse>
                  <n-collapse-item title="高级设置" name="1">
                    <n-grid x-gap="5">
                      <n-grid-item :span="8">
                        <n-form-item  label="并发数">
                          <n-input-number v-model:value="resourceForm.coreSize" default-value="2" clearable placeholder="请输入并发数"/>
                        </n-form-item>
                      </n-grid-item>
                      <n-grid-item :span="8">
                        <n-form-item label="队列长度" >
                          <n-input-number v-model:value="resourceForm.queueSize" default-value="50" clearable placeholder="请输入队列长度"/>
                        </n-form-item>
                      </n-grid-item>
                      <n-grid-item :span="8">
                        <n-form-item label="超时时间" >
                          <n-input-number v-model:value="resourceForm.timeoutMinutes" default-value="10" clearable placeholder="请输入超时时间">
                            <template #suffix>
                              分钟
                            </template>
                          </n-input-number>
                        </n-form-item>
                      </n-grid-item>
                    </n-grid>
                  </n-collapse-item>
                </n-collapse>
              </n-grid-item>
            </n-grid>
          </n-form>
          <n-form v-if="resourceForm.type=='SD' || resourceForm.type==='Fooocus' " label-placement="left" label-width="80" >
            <n-grid>
              <n-grid-item :span="24">
                <n-form-item  label="资源名称" path="resourceName">
                  <n-input v-model:value="resourceForm.resourceName" clearable placeholder="请输入资源名称"/>
                </n-form-item>
              </n-grid-item>
              <n-grid-item :span="24">
                <n-form-item label="资源地址">
                  <n-input  @update:value="extractUrlInfo" placeholder="请输入资源地址,进行解析！！例如:http://127.0.0.1:7860"/>
                </n-form-item>
              </n-grid-item>
              <n-grid-item :span="8">
                <n-form-item label="HTTPS" path="needSsl">
                  <n-radio-group
                      v-model:value="resourceForm.needSsl"
                      name="left-size"
                      style="margin-bottom: 12px"
                      :default-value="false"
                      :disabled="true"
                  >
                    <n-radio-button :value = 'true'>
                      是
                    </n-radio-button>
                    <n-radio-button :value="false">
                      否
                    </n-radio-button>
                  </n-radio-group>
                </n-form-item>
              </n-grid-item>
              <n-grid-item :span="8">
                <n-form-item label="host" path="host">
                  <n-input v-model:value="resourceForm.host" :disabled="true" />
                </n-form-item>
              </n-grid-item>
              <n-grid-item :span="8">
                <n-form-item label="port" path="port">
                  <n-input v-model:value="resourceForm.port" :disabled="true"/>
                </n-form-item>
              </n-grid-item>
              <n-grid-item :span="24">
                <n-collapse>
                  <n-collapse-item title="高级设置" name="1">
                   <n-grid>
                     <n-grid-item :span="8">
                       <n-form-item  label="并发数">
                         <n-input-number v-model:value="resourceForm.coreSize" default-value="2" clearable placeholder="请输入并发数"/>
                       </n-form-item>
                     </n-grid-item>
                     <n-grid-item :span="8">
                       <n-form-item label="队列长度" >
                         <n-input-number v-model:value="resourceForm.queueSize" default-value="50" clearable placeholder="请输入队列长度"/>
                       </n-form-item>
                     </n-grid-item>
                     <n-grid-item :span="8">
                       <n-form-item label="超时时间" >
                         <n-input-number v-model:value="resourceForm.timeoutMinutes" default-value="10" clearable placeholder="请输入超时时间">
                           <template #suffix>
                             分钟
                           </template>
                         </n-input-number>
                       </n-form-item>
                     </n-grid-item>
                    <n-grid-item :span="8">
                     <n-form-item :span="8" label="登录校验" path="isAuth" v-if="resourceForm.type==='SD'" >
                       <n-radio-group
                           v-model:value="resourceForm.isAuth"
                           name="left-size"
                           style="margin-bottom: 12px"
                           default-value="0"
                       >
                         <n-radio-button value="1">
                           是
                         </n-radio-button>
                         <n-radio-button value="0">
                           否
                         </n-radio-button>
                       </n-radio-group>
                     </n-form-item>
                    </n-grid-item>
                    <n-grid-item :span="8">
                      <n-form-item v-if="resourceForm.isAuth === '1'" label="账号" path="username">
                        <n-input v-model:value="resourceForm.username" clearable placeholder="请输入账号"/>
                      </n-form-item>
                    </n-grid-item>
                    <n-grid-item :span="8">
                       <n-form-item v-if="resourceForm.isAuth === '1'" label="密码" path="password">
                         <n-input v-model:value="resourceForm.password" clearable placeholder="请输入密码"/>
                       </n-form-item>
                    </n-grid-item>
                   </n-grid>
                  </n-collapse-item>
                </n-collapse>
              </n-grid-item>
            </n-grid>
          </n-form>
          <template #footer>
            <n-space>
              <n-button v-if="resourceForm.type!='MJ'" type="success" :loading="testConnectLoading" @click="resourceTestAtNoRegister(resourceForm)">
                连接测试
              </n-button>
              <n-button type="primary" @click="addOrUpdateResource">
                确定
              </n-button>
            </n-space>
          </template>
        </n-drawer-content>
      </n-drawer>

      <n-drawer v-model:show="modelManagerShow" :width="1000">
        <n-drawer-content title="模型管理" closable>
          <ModelManager :resourceId="selectdResourceId"/>
        </n-drawer-content>
      </n-drawer>

      <n-modal
          v-model:show="showPluginModal"
          class="custom-card"
          preset="card"
          style="width: 1200px;height: 750px"
          title="必要插件和模型检测"
          size="huge"
          :bordered="false"
      >
        <n-scrollbar style="height: 600px" trigger="none">
          <n-alert :show-icon="false" type="warning">
            <n-h6>请确保您已经安装以下插件以及模型,如果没有安装,在使用SD的过程中会有莫名的错误....</n-h6>

            该检测只会检测是否安装了插件，不会检测模型是否下载，请确保对应的模型已经成功下载并使用！！！</n-alert>
          <n-h6>插件检测</n-h6>
          <n-table :bordered="false" :single-line="false">
            <thead>
            <tr>
              <th style="width: 100px">检测</th>
              <th>插件名称</th>
              <th>中文名</th>
              <th>描述</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="plugin in selectedSD.pluginInfo.pluginTestResults">
              <td>
                <n-tag type="success" v-if="plugin.exist">已安装</n-tag>
                <n-tag type="error" v-else>检测失败</n-tag>

              </td>
              <td>{{plugin.pluginProjectName}}</td>
              <td>{{plugin.pluginName}}</td>
              <td>{{plugin.pluginDesc}}</td>
            </tr>
            </tbody>
          </n-table>

          <n-h6>ControlNet检测</n-h6>
          <n-table :bordered="false" :single-line="false">
            <thead>
            <tr>
              <th style="width: 100px">检测</th>
              <th>插件名称</th>
              <th>描述</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="plugin in selectedSD.pluginInfo.controlNetTestResults">
              <td>
                <n-tag type="success" v-if="plugin.exist">已安装</n-tag>
                <n-tag type="error" v-else>检测失败</n-tag>

              </td>
              <td>{{plugin.modelName}}</td>
              <td>{{plugin.modelDesc}}</td>
            </tr>
            </tbody>
          </n-table>
        </n-scrollbar>


      </n-modal>

    </div>
</template>

<script lang="ts" setup>
import {h, reactive, ref, onMounted, Component, watch} from 'vue'
import { NTag, NButton } from 'naive-ui'
import {resourceController} from '@/api/resource/resourceController.api'
import {mjControllerApi} from "@/api/mj/mjController.api";
import ModelManager from '@/views/pages/aiart/stablediffusion/modelManager.vue'


const tableLoading = ref(false)
const resourceInfo = ref([])
const modelManagerShow = ref(false)
const selectdResourceId = ref('')
const resourceModalShow = ref(false)

const selectedSD = ref(null)


import mjPng from '@/assets/images/mj.png'
import sdPng from '@/assets/images/sd.png'
import fooocusPng from '@/assets/images/fooocus.png'
import {sdControllerApi} from "@/api/sd/sdController.api";
const testConnectLoading = ref(false)
const addOrUpdateResourceLoading = ref(false)
const pluginLoading = ref(false)
const showPluginModal = ref(false)
const queryForm = reactive({
  type:'',
  name:''
})

const resourceForm = ref(reactive({
  coreSize : 1,
  queueSize : 5000,
  timeoutMinutes : 10,
  txt2ImgApiPath : '/sdapi/v1/txt2img',
  img2ImgApiPath : '/sdapi/v1/img2img',
  needSsl: false,
  isAuth: "0",
  type: "SD",
  isPublic: "0",
  status: "1",
  isDefault: "0",
  resourceName: '',
  username: '',
  password: '',
  host:'',
  port:'',
  guildId:'',
  channelId:'',
  userToken:'',
  proxyIp:'',
  proxyPort:'',
  id:''
}))



const initForm = (type:string) => {
  if (type ==='SD' || type ==='Fooocus'){
    resourceForm.value.id = ''
    resourceForm.value.coreSize = 2
    resourceForm.value.queueSize = 5000
    resourceForm.value.timeoutMinutes = 10
    resourceForm.value.txt2ImgApiPath = '/sdapi/v1/txt2img'
    resourceForm.value.img2ImgApiPath = '/sdapi/v1/img2img'
    resourceForm.value.needSsl = false
    resourceForm.value.isAuth = "0"
    resourceForm.value.type = "SD"
    resourceForm.value.isPublic = "0"
    resourceForm.value.status = "1"
    resourceForm.value.isDefault = "0"
    resourceForm.value.resourceName = ''
    resourceForm.value.proxyIp = ''
    resourceForm.value.proxyPort = ''
  }else if(type ==='MJ'){
    resourceForm.value.id = ''
    resourceForm.value.coreSize = 1
    resourceForm.value.queueSize = 500
    resourceForm.value.timeoutMinutes = 20
    resourceForm.value.isAuth = "0"
    resourceForm.value.type = "MJ"
    resourceForm.value.resourceName = ''
    resourceForm.value.guildId = ''
    resourceForm.value.channelId = ''
    resourceForm.value.userToken = ''
    resourceForm.value.proxyIp = ''
    resourceForm.value.proxyPort = ''
  }
}

const resourceEdit = (row:any) =>{
  resourceForm.value = {...row.obj}
  resourceModalShow.value = true
}

const resourceDeleteById = (row:any) => {
  window.$dialog.error({
    title: "温馨提醒",
    content: "删除操作不可逆，是否继续？",
    positiveText: "确定",
    negativeText: "取消",
    onPositiveClick: () => {
      resourceController.deleteResource(row.id).then((res:any) =>{
        if(res.code === 200){
          getDataList()
        }
      })
    }
  })
}


const resourceTest = (row:any)=>{
  if(row.type != 'SD' && row.type!='ChatGPT' && row.type !='Fooocus' && row.type !='MJ'){
    window.$message.warning("暂不支持测试")
    return
  }
  if(row.type ==='MJ'){
    row.loading = true
    mjControllerApi.reConnect().then((res:any) =>{
      if(res.code === 200){
        window.$message.success("连接中,请稍后!")
      }
    }).finally(()=>{
      row.loading = false
    })
  }else {
    row.loading = true
    resourceController.resourceTest(row.id).then((res: any) => {
      if (res.code === 200) {
        window.$message.success("连接成功!")
      } else {
        window.$message.error(res.msg)
      }
    }).finally(() => {
      row.loading = false
    })
  }
}
const resourceTestAtNoRegister = (row:any)=>{
  testConnectLoading.value=true
  resourceController.remoteResourceTestNoRegister(row).then((res: any) => {
    if (res.code === 200) {
      window.$message.success("连接成功!")
    } else {
      window.$message.error(res.msg)
    }
  }).finally(() => {
    testConnectLoading.value = false
  })
}


/**
 * 获取列表数据
 * @param data
 */
const getDataList = () => {
  tableLoading.value = true
  resourceController.getRemoteResourceInfo(queryForm).then((res: any) => {
    tableLoading.value = false
    if(res.code === 200) {
      resourceInfo.value = res.data.filter((item: any) => {
        return item.type === 'SD' || item.type === 'MJ' || item.type === 'Fooocus'
      })
      resourceInfo.value.forEach(item =>{
        if (item.type === 'SD'){
          testPlugin(item)
        }
      })
      // resourceInfo.value = res.data
    }
  }).catch((e: any) => {
    tableLoading.value = true
  })
}



onMounted(()=>{
  getDataList()
})

const extractUrlInfo = (url:string) =>{
  const regex = /^(?<protocol>https?):\/\/(?<host>[^\s\/:]+)(?::(?<port>\d+))?(\/[^\s]*)?/;
  const match = url.match(regex);

  if (match) {
    if (match.groups.port ==null || match.groups.port === undefined){
      match.groups.port = match.groups.protocol === 'https' ? '443' : '80'
    }
    const protocol = match.groups.protocol === 'https' ? 'HTTPS' : 'HTTP'
    const host = match.groups.host
    const port = match.groups.port
    console.log(protocol,host,port)
    resourceForm.value.host =host
    resourceForm.value.needSsl = (protocol === 'HTTPS')
    if (port == null || port === undefined){
      resourceForm.value.port = (protocol === 'https' ? '443' : '80')
    }else {
      resourceForm.value.port = port
    }
  }else {
    window.$message.warning("无法正确解析,请输入正确的地址或者自己填入")
  }
}


const addOrUpdateResource = () =>{
  addOrUpdateResourceLoading.value = true
  if (resourceForm.value.id){
    resourceController.updateResource(resourceForm.value).then((res:any) =>{
      if(res.code === 200){
        resourceModalShow.value = false
        getDataList()
      }
    }).finally(()=>{
      addOrUpdateResourceLoading.value = false
    })
  }else {
    resourceController.addSDResource(resourceForm.value).then((res: any) => {
      if (res.code === 200) {
        resourceModalShow.value = false
        getDataList()
      }
    }).finally(()=>{
      addOrUpdateResourceLoading.value = false
    })
  }
}


const testPlugin = (resource:any) =>{
  pluginLoading.value = true
  sdControllerApi.testPlugin(resource.id).then((res:any) =>{
    console.log(res)
    let warningCount = 0
    if (res.code == 200){
      // 查看错误的
      res.data.pluginTestResults.forEach((plugin:any) =>{
        if (!plugin.exist){
          warningCount++
        }
      })

      res.data.controlNetTestResults.forEach((plugin:any) =>{
        if (!plugin.exist){
          warningCount++
        }
      })

      resource.pluginInfo = res.data
      resource.pluginInfo.warningCount = warningCount
    }
  }).finally(()=>{
    pluginLoading.value = false
  })
}

</script>
